iT邦幫忙

2021 iThome 鐵人賽

DAY 19
0
自我挑戰組

馬克的軟體架構小筆記系列 第 19

30-19 之 Domain Layer - Repository

  • 分享至 

  • xImage
  •  

接下來我們要來談談,應該不少人常聽到的『 Repository 』這個東東,目前我先將他放在 3-Tier Layer 中的 DataSourceLayer 的部份,但是在書中是放在 :

Object-Relational Metadata Mapping Patterns

接下來我們來研究看看他到底是什麼。

什麼是 Repository 呢 ?

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

我個人的理解為 :

  • repository 介於 domain model 與 data mapper 之間。
  • 他存在的目的,可以想成,讓 db 操作『 更接近 domain model 』

data mapping 就是單純的資料庫操作,所以他提供的方法名很接近資料庫處理,例如 select、update 等。而 repository 傾向接近 domain 層,所以他的命名基本上是偏向 findByName、save 啥的。

我覺得這裡可以想簡單定義以為 repository 與 data mapper 的差別 :

  • data mapper : 單純的資料庫操作。
  • repository : data mapper 往上一層,更接近 domain 的東東,他是為了 domain 操作 db 而存在。

那這樣我可以理解為什麼要在書中把他定義在『 Object-Relational Metadata Mapping Patterns 』層級了。因為嚴格來說它是為了讓 domain layer 與 data source layer 中間在一個層級。

範例

// Domain Layer
class PersonDomain{
    id: string
    age: number
    name: string
    company: string
    constructor(id:string, age: number, name: string,company: string){
        this.id = id
        this.age = age
        this.name = name
        this.company = company
    }
    isAdult(): boolean{
        return this.age >= 18
    }
    isVIP(): boolean{
        return ['HAHOW','GOOGLE','KKBOX'].includes(this.company)
    }
}

// DataSource Layer

function _mockExecuteSelectSql(sql){
    return [
        {
            id: '1',
            name: 'mark',
            age: 18,
            company: 'HAHOW'
        }
    ] 
}

interface IPersonRepository{
    findById(id: string): PersonDomain
    findByCompany(company: string): PersonDomain[]
    save(person: PersonDomain)
}

class PersonRepository implements IPersonRepository {
    personMapper: IPersonMapper 
    constructor(personMapper: IPersonMapper){
        this.personMapper = personMapper
    }
    findById(id: string): PersonDomain{
        const result = this.personMapper.selectByQuery({
            id 
        })
        return result[0]
    }
    findByCompany(company: string): PersonDomain[]{
        const result = this.personMapper.selectByQuery({
            company 
        })
        return result 
    }
    save(person: PersonDomain): void{
        this.personMapper.insert(person)
    }
}

interface IPersonMapper{
    selectByQuery(query: any): PersonDomain[]
    insert(person: PersonDomain): void
}

class PersonMapper implements IPersonMapper {
    selectByQuery(query: any): PersonDomain[]{
        console.log('Connect to db for find')
        const querystring = query
        const resultSet: any = _mockExecuteSelectSql(querystring)
        const result = this.doLoad(resultSet)
        return result
    }
    insert(person: PersonDomain): void{

    }
    private doLoad(resultSet: any): PersonDomain[]{
        const result = []
        for (const data of resultSet) {
            result.push(new PersonDomain(data.id, data.age, data.name, data.company))
        }
        return result
    }
}

// App Layer
const personMapper: IPersonMapper = new PersonMapper()
const personRepository: IPersonRepository = new PersonRepository(personMapper)
const personsInCompany: PersonDomain[] = personRepository.findByCompany('HAHOW') 
if(personsInCompany.length >= 10) throw Error('公司人數已達限制')

const newPerson: PersonDomain = new PersonDomain(null, 18, 'Mark', 'HAHOW')
if(!newPerson.isAdult()) throw Error('要成年才能註冊喔')
personRepository.save(newPerson)

小總結

這個知識點可以用來解釋什麼現象

之前我一直在想,如果 domain 層有很多需要為了業務,而產生的一些 query,例如 SelectByNameAndAgeAndCompany 這種的,那是不是要在 data mapper 那『 為了業務而寫一個方法支援它呢 ? 』。

那這樣不就 domain model 與 dataMapper 耦合在一起了,理解了 repository 才知道這個層級就是為了解決這個問題。

這個知識點可以和以前的什麼知識連結呢 ?

上一篇文章中我們有問了一個問題如下 :

Repository 就是指 DataMapper 嗎 ?

不是,它比較接近 domain 層,它會將一些 domain 複雜的 query 資料庫操作,在 repository 裡處理,例如一些 n+1 的 i/o 操作,應該也會在這裡進行優化。

我要如何運用這個知識點 ?

  • 之後在設計 domain 與 db 操作之間,可以加上一層 repository 層,然後建立業務上所需要的一些查詢方法,而不用在 dataMapper 那為了業務,而新增方法。
  • 記好 repository 接近業務,所以命名時不要以 db 的操作來命名。

參考資料


上一篇
30-18 之 DataSource Layer- DataMapper
下一篇
30-20 之 Domain Layer - UnitOfWork
系列文
馬克的軟體架構小筆記29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言